package com.app.xinfadi.util;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.pm.Signature;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.media.AudioManager;
import android.media.MediaScannerConnection;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.opengl.GLES10;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.provider.MediaStore;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.ShareActionProvider;
import android.text.TextUtils;
import android.util.TypedValue;
import android.view.HapticFeedbackConstants;
import android.view.MotionEvent;
import android.view.SoundEffectConstants;
import android.view.View;
import android.view.ViewGroup;
import android.webkit.WebView;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

import com.app.xinfadi.BuildConfig;
import com.app.xinfadi.base.MyApplication;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.Closeable;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.microedition.khronos.opengles.GL10;
import javax.microedition.khronos.opengles.GL11;


public class Utility {

	private Utility() {
		// Forbidden being instantiated.
	}

	public static String encodeUrl(Map<String, String> param) {
		if (param == null) {
			return "";
		}

		StringBuilder sb = new StringBuilder();

		Set<String> keys = param.keySet();
		boolean first = true;

		for (String key : keys) {
			String value = param.get(key);
			// pain...EditMyProfileDao params' values can be empty
			if (!TextUtils.isEmpty(value) || key.equals("description") || key.equals("url")) {
				if (first) {
					first = false;
				} else {
					sb.append("&");
				}
				try {
					sb.append(URLEncoder.encode(key, "UTF-8")).append("=")
							.append(URLEncoder.encode(param.get(key), "UTF-8"));
				} catch (UnsupportedEncodingException e) {

				}
			}
		}

		return sb.toString();
	}

	public static Bundle decodeUrl(String s) {
		Bundle params = new Bundle();
		if (s != null) {
			String array[] = s.split("&");
			for (String parameter : array) {
				String v[] = parameter.split("=");
				try {
					params.putString(URLDecoder.decode(v[0], "UTF-8"), URLDecoder.decode(v[1], "UTF-8"));
				} catch (UnsupportedEncodingException e) {
					e.printStackTrace();
				}
			}
		}
		return params;
	}

	public static void closeSilently(Closeable closeable) {
		if (closeable != null) {
			try {
				closeable.close();
			} catch (IOException ignored) {

			}
		}
	}

	/**
	 * Parse a URL query and fragment parameters into a key-value bundle.
	 */
	public static Bundle parseUrl(String url) {
		// hack to prevent MalformedURLException
		url = url.replace("weiboconnect", "http");
		try {
			URL u = new URL(url);
			Bundle b = decodeUrl(u.getQuery());
			b.putAll(decodeUrl(u.getRef()));
			return b;
		} catch (MalformedURLException e) {
			return new Bundle();
		}
	}

	// public static void cancelTasks(MyAsyncTask... tasks) {
	// for (MyAsyncTask task : tasks) {
	// if (task != null) {
	// task.cancel(true);
	// }
	// }
	// }

	// public static boolean isTaskStopped(MyAsyncTask task) {
	// return task == null || task.getStatus() == MyAsyncTask.Status.FINISHED;
	// }

	// public static void stopListViewScrollingAndScrollToTop(ListView listView)
	// {
	// Runnable runnable = JavaReflectionUtility.getValue(listView,
	// "mFlingRunnable");
	// listView.removeCallbacks(runnable);
	// listView.setSelection(Math.min(listView.getFirstVisiblePosition(), 5));
	// listView.smoothScrollToPosition(0);
	// }

	public static int dip2px(int dipValue) {
		float reSize = MyApplication.getInstance().getResources().getDisplayMetrics().density;
		return (int) ((dipValue * reSize) + 0.5);
	}

	public static int px2dip(int pxValue) {
		float reSize = MyApplication.getInstance().getResources().getDisplayMetrics().density;
		return (int) ((pxValue / reSize) + 0.5);
	}

	public static float sp2px(int spValue) {
		return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, spValue, MyApplication.getInstance()
				.getResources().getDisplayMetrics());
	}

	public static int length(String paramString) {
		int i = 0;
		for (int j = 0; j < paramString.length(); j++) {
			if (paramString.substring(j, j + 1).matches("[Α-￥]")) {
				i += 2;
			} else {
				i++;
			}
		}

		if (i % 2 > 0) {
			i = 1 + i / 2;
		} else {
			i = i / 2;
		}

		return i;
	}

	public static boolean isConnected(Context context) {
		ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo networkInfo = cm.getActiveNetworkInfo();

		return networkInfo != null && networkInfo.isConnected();
	}

	public static boolean isWifi(Context context) {
		ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo networkInfo = cm.getActiveNetworkInfo();
		if (networkInfo != null && networkInfo.isConnected()) {
			if (networkInfo.getType() == ConnectivityManager.TYPE_WIFI) {
				return true;
			}
		}
		return false;
	}

	public static int getNetType(Context context) {
		ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo networkInfo = cm.getActiveNetworkInfo();
		if (networkInfo != null && networkInfo.isConnected()) {
			return networkInfo.getType();
		}
		return -1;
	}

	public static boolean isGprs(Context context) {
		ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
		NetworkInfo networkInfo = cm.getActiveNetworkInfo();
		if (networkInfo != null && networkInfo.isConnected()) {
			if (networkInfo.getType() != ConnectivityManager.TYPE_WIFI) {
				return true;
			}
		}
		return false;
	}

	public static boolean isSystemRinger(Context context) {
		AudioManager manager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
		return manager.getRingerMode() == AudioManager.RINGER_MODE_NORMAL;
	}

	// public static void configVibrateLedRingTone(Notification.Builder builder)
	// {
	// configRingTone(builder);
	// configLed(builder);
	// configVibrate(builder);
	// }

	// private static void configVibrate(Notification.Builder builder) {
	// if (SettingUtility.allowVibrate()) {
	// long[] pattern = {0, 200, 500};
	// builder.setVibrate(pattern);
	// }
	// }

	// private static void configRingTone(Notification.Builder builder) {
	// Uri uri = null;
	//
	// if (!TextUtils.isEmpty(SettingUtility.getRingtone())) {
	// uri = Uri.parse(SettingUtility.getRingtone());
	// }
	//
	// if (uri != null && isSystemRinger(MyApplication.getInstance())) {
	// builder.setSound(uri);
	// }
	// }

	// private static void configLed(Notification.Builder builder) {
	// if (SettingUtility.allowLed()) {
	// builder.setLights(Color.WHITE, 2000, 2000);
	// }
	// }

	public static String getPicPathFromUri(Uri uri, Activity activity) {
		String value = uri.getPath();

		if (value.startsWith("/external")) {
			String[] proj = { MediaStore.Images.Media.DATA };
			Cursor cursor = activity.managedQuery(uri, proj, null, null, null);
			int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
			cursor.moveToFirst();
			return cursor.getString(column_index);
		} else {
			return value;
		}
	}

	public static boolean isAllNotNull(Object... obs) {
		for (int i = 0; i < obs.length; i++) {
			if (obs[i] == null) {
				return false;
			}
		}
		return true;
	}

	// public static boolean isGPSLocationCorrect(GeoBean geoBean) {
	// double latitude = geoBean.getLat();
	// double longitude = geoBean.getLon();
	// if (latitude < -90.0 || latitude > 90.0) {
	// return false;
	// }
	// if (longitude < -180.0 || longitude > 180.0) {
	// return false;
	// }
	// return true;
	// }

	public static boolean isIntentSafe(Activity activity, Uri uri) {
		Intent mapCall = new Intent(Intent.ACTION_VIEW, uri);
		PackageManager packageManager = activity.getPackageManager();
		List<ResolveInfo> activities = packageManager.queryIntentActivities(mapCall, 0);
		return activities.size() > 0;
	}

	public static boolean isIntentSafe(Activity activity, Intent intent) {
		PackageManager packageManager = activity.getPackageManager();
		List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
		return activities.size() > 0;
	}

	@Deprecated
	public static boolean isGooglePlaySafe(Activity activity) {
		Uri uri = Uri.parse("http://play.google.com/store/apps/details?id=com.google.android.gms");
		Intent mapCall = new Intent(Intent.ACTION_VIEW, uri);
		mapCall.addFlags(Intent.FLAG_ACTIVITY_MULTIPLE_TASK);
		mapCall.setPackage("com.android.vending");
		PackageManager packageManager = activity.getPackageManager();
		List<ResolveInfo> activities = packageManager.queryIntentActivities(mapCall, 0);
		return activities.size() > 0;
	}

	public static boolean isSinaWeiboSafe(Activity activity) {
		Intent mapCall = new Intent("com.sina.weibo.remotessoservice");
		PackageManager packageManager = activity.getPackageManager();
		List<ResolveInfo> services = packageManager.queryIntentServices(mapCall, 0);
		return services.size() > 0;
	}

	public static String buildTabText(int number) {

		if (number == 0) {
			return null;
		}

		String num;
		if (number < 99) {
			num = "(" + number + ")";
		} else {
			num = "(99+)";
		}
		return num;
	}

	public static boolean isJB() {
		return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN;
	}

	public static boolean isJB1() {
		return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1;
	}

	public static boolean isJB2() {
		return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2;
	}

	// public static boolean isKK() {
	// return Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
	// }

	public static boolean isL() {
		return Build.VERSION.SDK_INT >= 20;
	}

	// public static int getScreenWidth() {
	// Activity activity = MyApplication.getInstance().getActivity();
	// if (activity != null) {
	// Display display = activity.getWindowManager().getDefaultDisplay();
	// DisplayMetrics metrics = new DisplayMetrics();
	// display.getMetrics(metrics);
	// return metrics.widthPixels;
	// }
	//
	// return 480;
	// }

	// public static int getScreenHeight() {
	// Activity activity = MyApplication.getInstance().getActivity();
	// if (activity != null) {
	// Display display = activity.getWindowManager().getDefaultDisplay();
	// DisplayMetrics metrics = new DisplayMetrics();
	// display.getMetrics(metrics);
	// return metrics.heightPixels;
	// }
	// return 800;
	// }

	public static Uri getLatestCameraPicture(Activity activity) {
		String[] projection = new String[] { MediaStore.Images.ImageColumns._ID, MediaStore.Images.ImageColumns.DATA,
				MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME, MediaStore.Images.ImageColumns.DATE_TAKEN,
				MediaStore.Images.ImageColumns.MIME_TYPE };
		final Cursor cursor = activity.getContentResolver().query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
				projection, null, null, MediaStore.Images.ImageColumns.DATE_TAKEN + " DESC");
		if (cursor.moveToFirst()) {
			String path = cursor.getString(1);
			return Uri.fromFile(new File(path));
		}
		return null;
	}

	public static void copyFile(InputStream in, File destFile) throws IOException {
		BufferedInputStream bufferedInputStream = new BufferedInputStream(in);
		FileOutputStream outputStream = new FileOutputStream(destFile);
		BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
		byte[] buffer = new byte[1024];
		int len;
		while ((len = bufferedInputStream.read(buffer)) != -1) {
			bufferedOutputStream.write(buffer, 0, len);
		}
		closeSilently(bufferedInputStream);
		closeSilently(bufferedOutputStream);
	}

	public static Rect locateView(View v) {
		int[] location = new int[2];
		if (v == null) {
			return null;
		}
		try {
			v.getLocationOnScreen(location);
		} catch (NullPointerException npe) {
			// Happens when the view doesn't exist on screen anymore.
			return null;
		}
		Rect locationRect = new Rect();
		locationRect.left = location[0];
		locationRect.top = location[1];
		locationRect.right = locationRect.left + v.getWidth();
		locationRect.bottom = locationRect.top + v.getHeight();
		return locationRect;
	}

	public static int countWord(String content, String word, int preCount) {
		int count = preCount;
		int index = content.indexOf(word);
		if (index == -1) {
			return count;
		} else {
			count++;
			return countWord(content.substring(index + word.length()), word, count);
		}
	}

	// public static void setShareIntent(Activity activity, ShareActionProvider
	// mShareActionProvider,
	// MessageBean msg) {
	// Intent shareIntent = new Intent(Intent.ACTION_SEND);
	// if (msg != null && msg.getUser() != null) {
	// shareIntent.setType("text/plain");
	// shareIntent.putExtra(Intent.EXTRA_TEXT,
	// "@" + msg.getUser().getScreen_name() + "：" + msg.getText());
	// if (!TextUtils.isEmpty(msg.getThumbnail_pic())) {
	// Uri picUrl = null;
	// String smallPath = FileManager.getFilePathFromUrl(msg.getThumbnail_pic(),
	// FileLocationMethod.picture_thumbnail);
	// String middlePath = FileManager.getFilePathFromUrl(msg.getBmiddle_pic(),
	// FileLocationMethod.picture_bmiddle);
	// String largePath = FileManager.getFilePathFromUrl(msg.getOriginal_pic(),
	// FileLocationMethod.picture_large);
	// if (ImageUtility.isThisBitmapCanRead(largePath)) {
	// picUrl = Uri.fromFile(new File(largePath));
	// } else if (ImageUtility.isThisBitmapCanRead(middlePath)) {
	// picUrl = Uri.fromFile(new File(middlePath));
	// } else if (ImageUtility.isThisBitmapCanRead(smallPath)) {
	// picUrl = Uri.fromFile(new File(smallPath));
	// }
	// if (picUrl != null) {
	// shareIntent.putExtra(Intent.EXTRA_STREAM, picUrl);
	// shareIntent.setType("image/*");
	// }
	// }
	// if (Utility.isIntentSafe(activity, shareIntent) && mShareActionProvider
	// != null) {
	// mShareActionProvider.setShareIntent(shareIntent);
	// }
	// }
	// }

	public static void setShareIntent(Activity activity, ShareActionProvider mShareActionProvider, String content) {
		Intent shareIntent = new Intent(Intent.ACTION_SEND);
		shareIntent.setType("text/plain");
		shareIntent.putExtra(Intent.EXTRA_TEXT, content);
		if (Utility.isIntentSafe(activity, shareIntent) && mShareActionProvider != null) {
			mShareActionProvider.setShareIntent(shareIntent);
		}
	}

	public static void buildTabCount(ActionBar.Tab tab, String tabStrRes, int count) {
		if (tab == null) {
			return;
		}
		String content = tab.getText().toString();
		int value = 0;
		int start = content.indexOf("(");
		int end = content.lastIndexOf(")");
		if (start > 0) {
			String result = content.substring(start + 1, end);
			value = Integer.valueOf(result);
		}
		if (value <= count) {
			tab.setText(tabStrRes + "(" + count + ")");
		}
	}

	public static void buildTabCount(TextView tab, String tabStrRes, int count) {
		if (tab == null) {
			return;
		}
		// String content = tab.getText().toString();
		// int value = 0;
		// int start = content.indexOf("(");
		// int end = content.lastIndexOf(")");
		// if (start > 0) {
		// String result = content.substring(start + 1, end);
		// value = Integer.valueOf(result);
		// }
		// if (value <= count) {
		tab.setText(" " + count + " " + tabStrRes);
		// }
	}

	// public static TimeLinePosition getCurrentPositionFromListView(ListView
	// listView) {
	// if (listView.getChildCount() == 0) {
	// LogUtil
	// .i("ListView child count is empty, maybe this ListView have not be visible to user");
	// return TimeLinePosition.empty();
	// }
	// LogUtil.i("ListView child count " + listView.getChildCount());
	// View view = listView.getChildAt(0);
	// int top = (view != null ? view.getTop() : 0);
	// /**
	// * warning: listView.getFirstVisiblePosition() return position include
	// headerview count (HeaderAdapter) and use java
	// * reflection to set mFirstPosition when call
	// setSelectionFromTop/setSelectionAfterHeaderView/setSelection
	// * see HeaderListView.java
	// *
	// */
	// int firstVisiblePosition = listView.getFirstVisiblePosition();
	// if (firstVisiblePosition < listView.getHeaderViewsCount()) {
	// /**
	// * for example, if header view count is 2, firstVisiblePosition is 1, then
	// listView getItemIdAtPosition(1)
	// * will return the second header view id -1, so we have to set
	// firstVisiblePosition to 2 to get your
	// * actual adapter's first item id
	// */
	// LogUtil.i("ListView first visible position is " + firstVisiblePosition
	// + " it  below header view count " + listView.getHeaderViewsCount()
	// + " so set header view count to it");
	// firstVisiblePosition = listView.getHeaderViewsCount();
	// }
	// LogUtil.i("ListView first visible position " + firstVisiblePosition);
	// long firstVisibleId = listView.getItemIdAtPosition(firstVisiblePosition);
	// LogUtil.i("ListView first visible id " + firstVisibleId);
	// return new TimeLinePosition(firstVisibleId, top,
	// listView.getFirstVisiblePosition());
	// }

	public static int getAdapterPositionFromItemId(BaseAdapter adapter, long itemId) {
		if (itemId == -1) {
			return -1;
		}
		for (int i = 0; i < adapter.getCount(); i++) {
			long id = adapter.getItemId(i);
			LogUtil.i("Position " + i + " item id " + id);
			if (id == itemId) {
				return i;
			}
		}
		return -1;
	}

	public static String getIdFromWeiboAccountLink(String url) {

		url = convertWeiboCnToWeiboCom(url);

		String id = url.substring("http://weibo.com/u/".length());
		id = id.replace("/", "");
		return id;
	}

	public static String getDomainFromWeiboAccountLink(String url) {
		url = convertWeiboCnToWeiboCom(url);

		final String NORMAL_DOMAIN_PREFIX = "http://weibo.com/";
		final String ENTERPRISE_DOMAIN_PREFIX = "http://e.weibo.com/";

		if (TextUtils.isEmpty(url)) {
			throw new IllegalArgumentException("Url can't be empty");
		}

		if (!url.startsWith(NORMAL_DOMAIN_PREFIX) && !url.startsWith(ENTERPRISE_DOMAIN_PREFIX)) {
			throw new IllegalArgumentException("Url must start with " + NORMAL_DOMAIN_PREFIX + " or "
					+ ENTERPRISE_DOMAIN_PREFIX);
		}

		String domain = null;
		if (url.startsWith(ENTERPRISE_DOMAIN_PREFIX)) {
			domain = url.substring(ENTERPRISE_DOMAIN_PREFIX.length());
		} else if (url.startsWith(NORMAL_DOMAIN_PREFIX)) {
			domain = url.substring(NORMAL_DOMAIN_PREFIX.length());
		}
		domain = domain.replace("/", "");
		return domain;
	}

	public static boolean isWeiboAccountIdLink(String url) {
		url = convertWeiboCnToWeiboCom(url);
		return !TextUtils.isEmpty(url) && url.startsWith("http://weibo.com/u/");
	}

	// todo need refactor...
	public static boolean isWeiboAccountDomainLink(String url) {
		if (TextUtils.isEmpty(url)) {
			return false;
		} else {
			url = convertWeiboCnToWeiboCom(url);
			boolean a = url.startsWith("http://weibo.com/") || url.startsWith("http://e.weibo.com/");
			boolean b = !url.contains("?");

			String tmp = url;
			if (tmp.endsWith("/")) {
				tmp = tmp.substring(0, tmp.lastIndexOf("/"));
			}

			int count = 0;
			char[] value = tmp.toCharArray();
			for (char c : value) {
				if ("/".equalsIgnoreCase(String.valueOf(c))) {
					count++;
				}
			}
			return a && b && count == 3 && !"http://weibo.com/pub".equals(tmp);
		}
	}

	// http://www.weibo.com/2125954191/Aj3W9z25s
	public static boolean isWeiboMid(String url) {
		if (TextUtils.isEmpty(url)) {
			return false;
		} else {
			url = convertWeiboCnToWeiboCom(url);
			boolean isUrlValidate = url.startsWith("http://weibo.com/") || url.startsWith("http://e.weibo.com/");

			if (!isUrlValidate) {
				return false;
			}

			if (url.endsWith("/")) {
				url = url.substring(0, url.length() - 1);
			}

			if (url.contains("http://weibo.com/")) {
				url = url.substring("http://weibo.com/".length(), url.length());
			} else {
				url = url.substring("http://e.weibo.com/".length(), url.length());
			}

			String[] result = url.split("/");

			return result != null && result.length == 2;
		}
	}

	public static String getMidFromUrl(String url) {
		url = convertWeiboCnToWeiboCom(url);

		if (url.endsWith("/")) {
			url = url.substring(0, url.length() - 1);
		}

		if (url.contains("http://weibo.com/")) {
			url = url.substring("http://weibo.com/".length(), url.length());
		} else {
			url = url.substring("http://e.weibo.com/".length(), url.length());
		}

		return url.split("/")[1];
	}

	private static String convertWeiboCnToWeiboCom(String url) {
		if (!TextUtils.isEmpty(url)) {
			if (url.startsWith("http://weibo.cn")) {
				url = url.replace("http://weibo.cn", "http://weibo.com");
			} else if (url.startsWith("http://www.weibo.com")) {
				url = url.replace("http://www.weibo.com", "http://weibo.com");
			} else if (url.startsWith("http://www.weibo.cn")) {
				url = url.replace("http://www.weibo.cn", "http://weibo.com");
			}
		}
		return url;
	}

	public static void vibrate(Context context, View view) {
		// Vibrator vibrator = (Vibrator)
		// context.getSystemService(Context.VIBRATOR_SERVICE);
		// vibrator.vibrate(30);
		view.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
	}

	public static void playClickSound(View view) {
		view.playSoundEffect(SoundEffectConstants.CLICK);
	}

	public static View getListViewItemViewFromPosition(ListView listView, int position) {
		return listView.getChildAt(position - listView.getFirstVisiblePosition());
	}

	// the position include HeadView
	public static void setListViewItemPosition(final ListView listView, final int itemPosition, final int top,
			final Runnable runnable) {

		listView.setSelectionFromTop(itemPosition, top);
		if (runnable != null) {
			runnable.run();
		}
	}

	// the position within the adapter's data set, will plus header view count
	public static void setListViewAdapterPosition(final ListView listView, final int adapterItemPosition,
			final int top, final Runnable runnable) {

		listView.setSelectionFromTop(adapterItemPosition + listView.getHeaderViewsCount(), top);
		LogUtil.i("ListView scrollTo " + (adapterItemPosition + listView.getHeaderViewsCount()) + " offset " + top);
		if (runnable != null) {
			runnable.run();
		}
	}

	// public static View getListViewFirstAdapterItemView(ListView listView) {
	// if (listView instanceof HeaderListView) {
	// HeaderListView headerListView = (HeaderListView) listView;
	// int childCount = headerListView.getChildCount();
	// for (int i = 0; i < childCount; i++) {
	// View childView = headerListView.getChildAt(i);
	// if (!headerListView.isThisViewHeader(childView)) {
	// return childView;
	// }
	// }
	//
	// //fallback to first view
	// LogUtil.v("all listview children are header view");
	// return headerListView.getChildAt(0);
	// }
	//
	// return listView.getChildAt(0);
	// }

	public static String getMotionEventStringName(MotionEvent event) {
		switch (event.getActionMasked()) {
		case MotionEvent.ACTION_DOWN:
			return "MotionEvent.ACTION_DOWN";
		case MotionEvent.ACTION_UP:
			return "MotionEvent.ACTION_UP";
		case MotionEvent.ACTION_CANCEL:
			return "MotionEvent.ACTION_CANCEL";
		case MotionEvent.ACTION_MOVE:
			return "MotionEvent.ACTION_MOVE";
		default:
			return "Other";
		}
	}

	public static boolean isDevicePort() {
		return MyApplication.getInstance().getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT;
	}

	public static void printStackTrace(Exception e) {
		if (BuildConfig.DEBUG) {
			e.printStackTrace();
		}
	}

	// public static boolean isTokenValid(AccountBean account) {
	// return !TextUtils.isEmpty(account.getAccess_token())
	// && (account.getExpires_time() == 0
	// || (System.currentTimeMillis()) < account.getExpires_time());
	// }

	// public static boolean isTokenExpiresInThreeDay(AccountBean account) {
	// long days = TimeUnit.MILLISECONDS
	// .toDays(account.getExpires_time() - System.currentTimeMillis());
	// return days > 0 && days <= 3;
	// }

	// public static long calcTokenExpiresInDays(AccountBean account) {
	// long days = TimeUnit.MILLISECONDS
	// .toDays(account.getExpires_time() - System.currentTimeMillis());
	// return days;
	// }

	// public static String convertStateNumberToString(Context context, String
	// numberStr) {
	// int thousandInt = 1000;
	// int tenThousandInt = thousandInt * 10;
	// int number = Integer.valueOf(numberStr);
	// if (number == tenThousandInt) {
	// return String
	// .valueOf((number / tenThousandInt) +
	// context.getString(R.string.ten_thousand));
	// }
	// if (number > tenThousandInt) {
	// String result = String
	// .valueOf((number / tenThousandInt) +
	// context.getString(R.string.ten_thousand));
	// if (number > tenThousandInt * 10) {
	// return result;
	// }
	// String thousand = String.valueOf(numberStr.charAt(numberStr.length() -
	// 4));
	// if (Integer.valueOf(thousand) != 0) {
	// result += thousand;
	// }
	// return result;
	// }
	// if (number > thousandInt) {
	// NumberFormat nf = NumberFormat.getNumberInstance();
	// return nf.format(Long.valueOf(number));
	// }
	// return String.valueOf(number);
	// }

	// public static void showExpiredTokenDialogOrNotification() {
	// final Activity activity =
	// MyApplication.getInstance().getCurrentRunningActivity();
	// boolean currentAccountTokenIsExpired = true;
	// AccountBean currentAccount =
	// MyApplication.getInstance().getAccountBean();
	// if (currentAccount != null) {
	// currentAccountTokenIsExpired = !Utility.isTokenValid(currentAccount);
	// }
	//
	// if (currentAccountTokenIsExpired && activity != null && !MyApplication
	// .getInstance().tokenExpiredDialogIsShowing) {
	// if (activity.getClass() == AccountActivity.class) {
	// return;
	// }
	// if (activity.getClass() == OAuthActivity.class) {
	// return;
	// }
	// if (activity.getClass() == BlackMagicActivity.class) {
	// return;
	// }
	//
	// if (activity.getClass() == SSOActivity.class) {
	// return;
	// }
	//
	// final AccountBean needRefreshTokenAccount = currentAccount;
	//
	// activity.runOnUiThread(new Runnable() {
	// @Override
	// public void run() {
	// new AlertDialog.Builder(activity).setTitle(R.string.dialog_title_error)
	// .setMessage(R.string.your_token_is_expired)
	// .setPositiveButton(R.string.logout_to_login_again,
	// new DialogInterface.OnClickListener() {
	// @Override
	// public void onClick(DialogInterface dialog, int which) {
	// activity.startActivity(
	// AccountActivity
	// .newIntent(needRefreshTokenAccount));
	// activity.finish();
	// MyApplication.getInstance().tokenExpiredDialogIsShowing
	// = false;
	// }
	// }).setOnCancelListener(new DialogInterface.OnCancelListener() {
	// @Override
	// public void onCancel(DialogInterface dialog) {
	// //do nothing
	// }
	// }).show();
	// MyApplication.getInstance().tokenExpiredDialogIsShowing = true;
	// }
	// });
	// } else if (!currentAccountTokenIsExpired || activity == null) {
	//
	// Intent i = AccountActivity.newIntent();
	// i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP |
	// Intent.FLAG_ACTIVITY_NEW_TASK);
	// PendingIntent pendingIntent = PendingIntent
	// .getActivity(MyApplication.getInstance(), 0, i,
	// PendingIntent.FLAG_UPDATE_CURRENT);
	//
	// Notification.Builder builder = new
	// Notification.Builder(MyApplication.getInstance())
	// .setContentTitle(MyApplication.getInstance().getString(R.string.login_again))
	// .setContentText(MyApplication.getInstance()
	// .getString(R.string.have_account_whose_token_is_expired))
	// .setSmallIcon(R.drawable.ic_notification)
	// .setAutoCancel(true)
	// .setContentIntent(pendingIntent)
	// .setOnlyAlertOnce(true);
	// NotificationManager notificationManager = (NotificationManager)
	// MyApplication
	// .getInstance()
	// .getSystemService(Context.NOTIFICATION_SERVICE);
	// notificationManager.notify(NotificationServiceHelper.getTokenExpiredNotificationId(),
	// builder.build());
	// } else if (MyApplication.getInstance().tokenExpiredDialogIsShowing) {
	// NotificationManager notificationManager = (NotificationManager)
	// MyApplication
	// .getInstance()
	// .getSystemService(Context.NOTIFICATION_SERVICE);
	// notificationManager.cancel(NotificationServiceHelper.getTokenExpiredNotificationId());
	// }
	// }

	public static int getMaxLeftWidthOrHeightImageViewCanRead(int heightOrWidth) {
		// 1pixel==4bytes
		// http://stackoverflow.com/questions/13536042/android-bitmap-allocating-16-bytes-per-pixel
		// http://stackoverflow.com/questions/15313807/android-maximum-allowed-width-height-of-bitmap
		int[] maxSizeArray = new int[1];
		GLES10.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxSizeArray, 0);

		if (maxSizeArray[0] == 0) {
			GLES10.glGetIntegerv(GL11.GL_MAX_TEXTURE_SIZE, maxSizeArray, 0);
		}
		int maxHeight = maxSizeArray[0];
		int maxWidth = maxSizeArray[0];

		return (maxHeight * maxWidth) / heightOrWidth;
	}

	// sometime can get value, sometime can't, so I define it is 2048x2048
	public static int getBitmapMaxWidthAndMaxHeight() {
		int[] maxSizeArray = new int[1];
		GLES10.glGetIntegerv(GL10.GL_MAX_TEXTURE_SIZE, maxSizeArray, 0);

		if (maxSizeArray[0] == 0) {
			GLES10.glGetIntegerv(GL11.GL_MAX_TEXTURE_SIZE, maxSizeArray, 0);
		}
		// return maxSizeArray[0];
		return 2048;
	}

	@SuppressLint("NewApi")
	public static void recycleViewGroupAndChildViews(ViewGroup viewGroup, boolean recycleBitmap) {
		for (int i = 0; i < viewGroup.getChildCount(); i++) {

			View child = viewGroup.getChildAt(i);

			if (child instanceof WebView) {
				WebView webView = (WebView) child;
				webView.loadUrl("about:blank");
				webView.stopLoading();
				continue;
			}

			if (child instanceof ViewGroup) {
				recycleViewGroupAndChildViews((ViewGroup) child, true);
				continue;
			}

			if (child instanceof ImageView) {
				ImageView iv = (ImageView) child;
				Drawable drawable = iv.getDrawable();
				if (drawable instanceof BitmapDrawable) {
					BitmapDrawable bitmapDrawable = (BitmapDrawable) drawable;
					Bitmap bitmap = bitmapDrawable.getBitmap();
					if (recycleBitmap && bitmap != null) {
						bitmap.recycle();
					}
				}
				iv.setImageBitmap(null);
				iv.setBackground(null);
				continue;
			}

			child.setBackground(null);
		}

		viewGroup.setBackground(null);
	}

//	public static boolean doThisDeviceOwnNavigationBar(Context context) {
//		boolean hasMenuKey = ViewConfiguration.get(context).hasPermanentMenuKey();
//		boolean hasBackKey = KeyCharacterMap.deviceHasKey(KeyEvent.KEYCODE_BACK);
//
//		return !hasMenuKey && !hasBackKey;
//	}

	/**
	 * https://svn.apache.org/repos/asf/cayenne/main/branches/cayenne-jdk1.5-
	 * generics
	 * -unpublished/src/main/java/org/apache/cayenne/conf/Rot47PasswordEncoder
	 * .java
	 */
	public static String rot47(String value) {
		int length = value.length();
		StringBuilder result = new StringBuilder();

		for (int i = 0; i < length; i++) {
			char c = value.charAt(i);

			// Process letters, numbers, and symbols -- ignore spaces.
			if (c != ' ') {
				// Add 47 (it is ROT-47, after all).
				c += 47;

				// If character is now above printable range, make it printable.
				// Range of printable characters is ! (33) to ~ (126). A value
				// of 127 (just above ~) would therefore get rotated down to a
				// 33 (the !). The value 94 comes from 127 - 33 = 94, which is
				// therefore the value that needs to be subtracted from the
				// non-printable character to put it into the correct printable
				// range.
				if (c > '~') {
					c -= 94;
				}
			}

			result.append(c);
		}

		return result.toString();
	}

	// if app's certificate md5 is correct, enable Crashlytics crash log
	// platform, you should not modify those md5 values
	public static boolean isCertificateFingerprintCorrect(Context context) {
		try {
			PackageManager pm = context.getPackageManager();
			String packageName = context.getPackageName();
			int flags = PackageManager.GET_SIGNATURES;

			PackageInfo packageInfo = pm.getPackageInfo(packageName, flags);

			Signature[] signatures = packageInfo.signatures;

			byte[] cert = signatures[0].toByteArray();

			String strResult = "";

			MessageDigest md;

			md = MessageDigest.getInstance("MD5");
			md.update(cert);
			for (byte b : md.digest()) {
				strResult += Integer.toString(b & 0xff, 16);
			}
			strResult = strResult.toUpperCase();
			// debug
			if ("DE421D82D4BBF9042886E72AA31FE22".toUpperCase().equals(strResult)) {
				return false;
			}
			// relaease
			if ("C96155C3DAD4CA1069808FBAC813A69".toUpperCase().equals(strResult)) {
				return true;
			}
			LogUtil.e(strResult);
		} catch (NoSuchAlgorithmException ex) {
			ex.printStackTrace();
		} catch (PackageManager.NameNotFoundException ex) {
			ex.printStackTrace();
		}

		return false;
	}

	// public static void
	// unregisterReceiverIgnoredReceiverNotRegisteredException(Context context,
	// RecordOperationAppBroadcastReceiver broadcastReceiver) {
	// if (broadcastReceiver == null || broadcastReceiver.hasUnRegistered() ||
	// !broadcastReceiver
	// .hasRegistered()) {
	// return;
	// }
	// try {
	// context.getApplicationContext().unregisterReceiver(broadcastReceiver);
	// broadcastReceiver.setHasUnRegistered(true);
	// } catch (IllegalArgumentException receiverNotRegisteredException) {
	// receiverNotRegisteredException.printStackTrace();
	// }
	// }

	// public static void
	// registerReceiverIgnoredReceiverHasRegisteredHereException(Context
	// context,
	// RecordOperationAppBroadcastReceiver broadcastReceiver, IntentFilter
	// intentFilter) {
	// if (broadcastReceiver == null || broadcastReceiver.hasRegistered()
	// || intentFilter == null) {
	// return;
	// }
	// try {
	// context.getApplicationContext().registerReceiver(broadcastReceiver,
	// intentFilter);
	// broadcastReceiver.setHasRegistered(true);
	// } catch (AndroidRuntimeException receiverHasRegisteredException) {
	// receiverHasRegisteredException.printStackTrace();
	// }
	// }

	public static void runUIActionDelayed(Runnable runnable, long delayMillis) {
		new Handler(Looper.getMainLooper()).postDelayed(runnable, delayMillis);
	}

	public static void forceRefreshSystemAlbum(String path) {
		final BitmapFactory.Options options = new BitmapFactory.Options();
		options.inJustDecodeBounds = true;
		BitmapFactory.decodeFile(path, options);
		String type = options.outMimeType;

		MediaScannerConnection
				.scanFile(MyApplication.getInstance(), new String[]{path}, new String[]{type}, null);
	}

	public static boolean isDebugMode() {
		return BuildConfig.DEBUG;
	}

	// long click link(schedule show dialog event), press function button(onPause
	// onSaveInstance), show dialog,then crash....
	// executePendingTransactions still occur crash
	public static void forceShowDialog(FragmentActivity activity, DialogFragment dialogFragment) {
		try {
			dialogFragment.show(activity.getSupportFragmentManager(), "");
			activity.getSupportFragmentManager().executePendingTransactions();
		} catch (Exception ignored) {

		}
	}

	public static Bitmap getBitmapFromView(View view) {

		Bitmap b = Bitmap.createBitmap(view.getWidth(), view.getHeight(), Bitmap.Config.ARGB_8888);
		Canvas c = new Canvas(b);
		c.translate(-view.getScrollX(), -view.getScrollY());
		view.draw(c);
		return b;
	}

	// public static void removeDuplicateAndSortStatus(List<MessageBean> data) {
	// HashSet<MessageBean> hashSet = new HashSet<>();
	// hashSet.addAll(data);
	// data.clear();
	// data.addAll(hashSet);
	// sortData(data);
	// }

	// public static void removeDuplicateAndSortComment(List<CommentBean> data)
	// {
	// HashSet<CommentBean> hashSet = new HashSet<>();
	// hashSet.addAll(data);
	// data.clear();
	// data.addAll(hashSet);
	// sortData(data);
	// }

	// public static void sortData(List<? extends ItemBean> data) {
	// Collections.sort(data, mComparator);
	// }

	// private static Comparator<ItemBean> mComparator = new
	// Comparator<ItemBean>() {
	// @Override
	// public int compare(ItemBean left, ItemBean right) {
	// return (int) (right.getMills() - left.getMills());
	// }
	// };

	/**
	 * 获取Attr的值
	 * @param context
	 * @param attr
	 * @return
	 */
	public static int getThemeAttributeDimensionSize(Context context, int attr)
	{
		TypedArray a = null;
		try{
			a = context.getTheme().obtainStyledAttributes(new int[] { attr });
			return a.getDimensionPixelSize(0, 0);
		}finally{
			if(a != null){
				a.recycle();
			}
		}
	}
}
